11 - Input Devices

Sensing a Magnetic Field with a Hall Sensor

This week was one of the few were I already knew what I would like to exactly do before the week started. As this topic is actually the last week with electronics, I already previously designed and manufactured a board for my final project that should be capable of reading the output of a Hall sensor. For this, I already had to pick a certain sensor, which I will connect to the board this week. This weeks's assignment were:

  • Group Assignment
    • Probe an input device's analog levels and digital signals
  • Individual Assignment
    • Measure something: Add a sensor to a microcontroller board that you have designed and read it

Group Assignment

For the group assignment, we had to probe an output of an input device. This should be done for one digital and one analog output. In this case, we did this only for one sensor module that supplies the user with an analog and a digital output, namely the same hall sensor, that I have been using for my individual assignment (see below).

In principle, we connected the break out board to a power supply via the power and ground pins of a microcontroller. Additionally, the digital as well as analog output of the module were joined with a digital and analog channel of an oscilloscope. With the latter the digital and analog outputs were measured while approaching and withdrawing the sensor with a magnet. Here, the analog output of the sensor was a true analog value which is depending on the pole of the magnet and its distance in all spatial directions. The sensitivity and by this the reaction of the sensor to the magnet can be increased and decreased by turning a potentiometer on the sensor's break out board.

The output of the digital pin was quite surprising as it actually is something like a PWM signal just not with a rectangular wave patter but rather a sawtooth pattern with curved edges. Have a look at the image to see the output.

The amplitude of the digital signal is about 3.9 V with a duty cycle of about 70.1% for a continuous pattern.

For the details on the group assignment, please refer to our group page. You can find it here.

Oscilloscope Showing the Digital Output

Individual Assignment

This week's task were simple for me as I already made a big effort in the electronics design. Here, I designed a PCB for my final project according to the external components I needed. However, to do this, I firstly researched and identified which components are the best to use with regards to availability. Hence, for this week, I already had a board and a sensor, that I wanted to connect.

The board, I was using for this assignment is the one I made in the electronics design week. As a sensor, I used a Hall sensor that should be able to measure the strength of a magnetic field qualitatively. For my final project, the magnetic field is generated by a diametrical magnet that is mounted to the rotating shaft. By measuring the field strength, the angle of the rotation should be sensed.

Breakout Board with Hall Sensor (Black Box in the Top)

However, to measure something with this sensor, I firstly had to establish a serial communication between the board and my computer, then take some preliminary measurements and lastly actually measure the strength of the magnetic field qualitatively.

Establishing a Serial Communication

To allow for measuring something with the Hall sensor and actually display the readings, I need an output device, preferably a display that can show the readings. However, instead of connecting such a component directly to the board, I decided to let the board send the readings to the serial monitor of the Arduino IDE such that my computer can display the readings.

In order to establish a serial communication via UART, I firstly researched on how to program that with the Arduino IDE. Here, I specifically searched for a sketch that also allows me to specify the Rx and Tx pins as I did not know whether the they are already pre-configured. Here, I found this documentation where they used the SoftwareSerial library.

I copied the code from that website into a new Arduino sketch. Then, I only added a delay to send the message "100" every half of a second abd few lines to make an LED flash whenever a serial message is send. The pin definitions were set in accordance to the pinout that Arduino uses for referencing it as shown here. Next, I setup the Arduino IDE and connected the board to my computer via a programmer board and the UPDI pins as shown here. Lastly, I uploaded the Arduino sketch to the microcontroller. The code is shown below.

#include "SoftwareSerial.h"

// Declare and initialize UART pins
const int rx_pin = 4;
const int tx_pin = 5;

// Declare and initialize led pin
const int led_pin = 9;

// Create new serial with specified UART pins
SoftwareSerial mySerial(rx_pin , tx_pin);


void setup(){ 
	// Set the pin modes of UART pins
	pinMode(rx_pin, INPUT); // Receiving requires input
	pinMode(tx_pin, OUTPUT); // Transmitting requires output

	// Set led as output
	pinMode(led_pin, OUTPUT);

	// Start the serial communication at 9600 bits/sec
	mySerial.begin(9600);
}


void loop(){ 
	mySerial.println("100"); // Send the message "100"

	// Flash the LED
	digitalWrite(led_pin,HIGH);
	delay(100);
	digitalWrite(led_pin,LOW);

	// Wait some time (500ms in total)
	delay(400);
}

As I saw the built-in LED flashing, I continued with establishing a physical serial connection. Here, I firstly removed all connections from the board including the programmer board and secondly connected an FTDI module to the FTDI pins of the board. Then, I connected the FTDI module to my computer with a USB cable. This setup is shown in the following picture.

Connecting the Board to an FTDI Module

As soon as I had connected the FTDI module to my computer, the power LED turned on. Slightly later, the blue built-in LED on the board started to flash indicating whenever a serial message was sent.

Next, I wanted to open the serial monitor of the Arduino IDE by going to Tools > Serial Monitor. However, this gave me an error message that the board at the chosen COM is not available. Therefore, I changed the port to another one that appeared only after connecting the board to my computer via the FTDI module. This now allowed me to open the serial monitor. Lastly, I specified the baud rate to the 9600 bits per second that I defined in the sketch for serial communication.

As you can see in the video below, this communication worked flawless. The LED flashed every time a serial message was received.

Serial Communication with the Microcontroller Receiving "100" every Half Second on My Computer

Preliminary Measurements with a Hall Sensor

After having established a serial communication with the board, I wanted to achieve that the message consists of a reading of the sensor. For this, I slightly modified the code by adding a variable for the pin of the hall sensor and modifying the pin mode. Just before a serial message is sent, the analog value of the pin is measured and stored in the variable val which is then sent via the serial communication.

Next, I connected the board to my computer via the programmer board and UPDI connections again and set the port to the right COM. Then, I uploaded the modified sketch shown below.

#include "SoftwareSerial.h"

// Declare and initialize UART pins
const int rx_pin = 4;
const int tx_pin = 5;

// Declare and initialize led and hall sensor pin
const int led_pin = 9;
const int hall_pin = 8;

// Create new serial with specified UART pins
SoftwareSerial mySerial(rx_pin , tx_pin);


void setup(){ 
	// Set the pin modes of UART pins
	pinMode(rx_pin, INPUT); // Receiving requires input
	pinMode(tx_pin, OUTPUT); // Transmitting requires output

	// Set led as output
	pinMode(led_pin, OUTPUT);

	// Set sensor as input
	pinMode(hall_pin, INPUT);

	// Start the serial communication at 9600 bits/sec
	mySerial.begin(9600);
}


void loop(){ 
	// Read the analog value of the pin and send it via serial communication
	int val = analogRead(hall_pin);
	mySerial.println(val);

	// Flash the LED
	digitalWrite(led_pin,HIGH);
	delay(100);
	digitalWrite(led_pin,LOW);

	// Wait some time (500ms in total)
	delay(400);
}

After the upload, I disconnected the programmer board and connected the FTDI module to my computer. Next, I attached the Hall sensor to my board. For this, three cables are needed, one for VCC and the ground respectively and the last one for the data. This sensor offers two data connections. One of them is a digital output signal that switches between a high an low voltage level and by this senses whether there is a magnet close by or not. The other output signal is analog which also allows to estimate the magnetic field strength. Here, I chose the latter as this also allows to sense the orientation of a magnet as needed for my final project.

The PCB Connected to an FTDI Module (Bottom) and a Hall Sensor (Top)

In the Arduino IDE, I again changed the port and opened the serial plotter via Tools > Serial Plotter. Then, I used a magnet that I found on a whiteboard and approached the hall sensor with one flat side and consecutively with the opposite side as shown in the video below.

Moving the Magnet

As shown in the image below from the serial plotter, the baseline of the sensor without any magnet close to it, the sensor's reading is at about 550. When one side of the magnet approaches the sensor, the measurements increase drastically. Vice versa, if the other side of the magnet, i.e. the opposite polarization, approaches the sensor, the measurements decrease, however to not such a big extent as the peak. This might be due to the cap on the magnet, that prevents me to approach the magnet as closely as with the other side.

Output of the Hall Sensor with Low Time-Resolution

Measuring the Strength of an Magnetic Field Qualitatively

After I successfully tested the sketch and the circuit's connection, I continued with a more sophisticated program. Here, I aimed for a higher time-wise resolution. Therefore, I deleted everything regarding the LED and decreased the pause in the end of the loop.

To upload the modified sketch as shown below, I again connected the board via a programmer board and UPDI pins. Then, I selected the right port in the Arduino IDE and uploaded the program.

#include "SoftwareSerial.h"

// Declare and initialize UART pins
const int rx_pin = 4;
const int tx_pin = 5;

// Declare and initialize hall sensor pin
const int hall_pin = 8;

// Create new serial with specified UART pins
SoftwareSerial mySerial(rx_pin , tx_pin);


void setup(){ 
	// Set the pin modes of UART pins
	pinMode(rx_pin, INPUT); // Receiving requires input
	pinMode(tx_pin, OUTPUT); // Transmitting requires output

	// Set sensor as input
	pinMode(hall_pin, INPUT);

	// Start the serial communication at 9600 bits/sec
	mySerial.begin(9600);
}


void loop(){ 
	// Read the analog value of the pin and send it via serial communication
	int val = analogRead(hall_pin);
	mySerial.println(val);

	// Add a small pause of 50ms
	delay(50);
}

Once the upload was complete, I disconnected the programmer board, connected the FTDI module to the PCB and my computer and selected the right port in the Arduino IDE. Lastly, I opened the serial plotter again and repeated moving the magnet to the sensor, first facing the one side and consecutively the other side.

As you can see in the image of the plotter below, many more measurements were taken while the magnet was moved in approximately the same speed. This also allows to see more details on the exact movement.

Output of the Hall Sensor with High Time-Resolution

Angle Measurements with a Hall Sensor

With the setup above, I investigated the functional principles of the sensor. In the future, for my final project, I would like to use this sensor for angle measurements. Here, the magnet should be mounted to a rotating shaft and by this rotate according to the shaft. The sensor should then measure the magnetic field strength. With this, angle measurements should be possible.

To make this possible, the magnet must be oriented such that a rotation should induce a change of the magnetic field strength. Here, the easiest would be to use a diametric magnet, where each pole consist of an extruded semicircle as shown in the image.

Diametric Magnet with Semicircular Poles

To finish this part with appropriate angle measurements, I bought diametric magnets. Next, I had to design and manufacture a magnet holder to hold the magnet at the end of the shaft. With this, I was then able to record the angle of a shaft that is continuously rotated by the motor.

Design and Manufacturing of the Magnet Holder

The magnet holder was designed in Fusion 360. I started by drawing a ring on the XY plane with an inner diameter of 10 mm, i.e. the outer diameter of the diametric magnet as well as the shaft, plus a tolerance of 0.4 mm. The thickness of the ring was set to be 2.5 mm. I extruded it by 23 mm and closed one of the ends with a 10 mm extrusion. Next, I drew another ring on the open end of the structure with the same inner diameter and a wall thickness of 10 mm. This ring was extruded by another 10 mm generating the raw structure of the magnet holder.

Next, to keep the magnet holder and the magnet itself attached to the shaft, I made rectangular inserts for nuts and orthogonally to it circular inserts for the according bolts. The bolts can be used as set screws to tighten the 3D printed part against the shaft and the magnet.

Lastly, I added a chamfer to between the two rings of the raw structure to make a smoother finish.

Raw Structure of the Magnet Holder

Added Nut and Bolt Inserts

Added Chamfer

From Fusion, this design was exported as an .stl file which was imported into the software Ultimaker Cura. Here, the machine code for an Ultimaker S5 was generated using the profile "Normal - 0.15 mm" without any supports and black Ultimaker PLA as a material. The generated file was brought to the 3D printer via a flash drive where it was started by selecting the file and confirming the start.

Programming Motor Rotations and Angle Measurements

Next, I programmed the board with the setup shown above. The code that I uploaded to the board is basically the same as in the previous section but also performs a motor step right before reading the analog value of the hall sensor and sending the reading to my computer via the serial communication. However, the sensor readings are averaged over ten measurements.

#include "SoftwareSerial.h"

// Declare and initialize UART pins
const int rx_pin = 4;
const int tx_pin = 5;

// Declare and initialize hall sensor pin
const int hall_pin = 8;

// Define pin numbers for motor driver
const int dirPin = 1; // direction
const int stepPin = 2; // step
const int enaPin = 3; // enable

// set number of steps that the motor should rotate
const int steps = 16*200*2; 

int sum = 0;

// Create new serial with specified UART pins
SoftwareSerial mySerial(rx_pin , tx_pin);

void setup() {
	// Set the pin modes of UART pins
	pinMode(rx_pin, INPUT); // Receiving requires input
	pinMode(tx_pin, OUTPUT); // Transmitting requires output

	// Set sensor as input
	pinMode(hall_pin, INPUT);

	// Start the serial communication at 9600 bits/sec
	mySerial.begin(9600);
	
	// Define all pins for motor driver as output
	pinMode(stepPin,OUTPUT);
	pinMode(dirPin,OUTPUT);
	pinMode(enaPin,OUTPUT);

// Enable the motor driver
	digitalWrite(enaPin,LOW);
	digitalWrite(dirPin,HIGH); // Set the rotation to one particular direction
}

void loop() {
	// Perform a certain number of steps
	for(int x = 0; x < steps; x++) {
		// Generate a pulse
		digitalWrite(stepPin,HIGH);
		delayMicroseconds(700);
		digitalWrite(stepPin,LOW);
		delayMicroseconds(700);
		
		// Read the analog value of the pin and send it via serial communication
		int val = analogRead(hall_pin);
		// Average the readings over ten points
		if (x%10 == 0){
			mySerial.println(sum/10);
			sum = 0;
		}
		else {
			sum = sum + val;
		}
	}
}
Setup for Angle Measurements

The setup to measure the angle that is generated by a continuous rotation of a motor consist also of the serial connection (see above). Additionally, the Hall sensor is connected to it (see above). In addition however, the stepper motor and a bench power supply is connected as shown in the assignment on output devices. Lastly, I attached the magnet holder with a magnet to the motor shaft. A photo of the complete setup including the programmer board is shown below.

During the measurements, I tried to hold my hand as steady as possible to keep a constant distant to the magnet.

Setup for Angle Measurements

Results of Angle Measurements

Once everything was setup, I set the bench power supply to 24 V and a load-dependent current. As soon as the power was supplied to the motor, it started rotating as shown in the video.

Motor Rotating During the Angle Measurements

In addition, I opened the serial plotter via Tools > Serial Plotter which showed the sensor readings below. The deviations of the slope in the readings correspond to an off-centric rotation of the magnet as the magnet holder is designed for a 10 mm shaft.

Results of Measuring the Angle of the Rotation

Source Code for Download